package utool

import (
	"encoding/json"
	"fmt"
	"reflect"
	"strings"
)

func (a *App) JsonToStructGo(str string) H {

	var j = make(map[string]interface{}, 0)
	err := json.Unmarshal([]byte(str), &j)
	if err != nil {
		return M{
			"code": 0,
			"msg":  err.Error(),
		}
	}

	var structStr = ""
	for k, v := range j {
		structStr += parseStruct(k, v, 0) + "\n"
	}
	res := fmt.Sprintf("type GenStruct struct {\n%v}", structStr)

	return M{
		"code": 1,
		"msg":  "success",
		"data": res,
	}
}



func pasrKey(k string) string {
	b := []byte(k)
	if b[0] >= 97 && b[0] <= 122 {
		b[0] -= 32
	}
	for i := 0; i < len(b); i++ {
		if b[i] == 46 {
			b[i+1] -= 32
		}
	}
	return strings.ReplaceAll(string(b), ".", "")
}

func parseStruct(k string, v interface{}, dep int) (str string) {

	for i := 0; i < (dep+1)*4; i++ {
		str += " "
	}
	str += pasrKey(k)

	if v == nil {
		str = fmt.Sprintf("%v interface{} `json:\"%v\"`", str, k)
		return
	}

	kind := reflect.TypeOf(v).Kind()

	switch kind {
	case reflect.Map:
		s := subMap(v, dep+2)
		str = fmt.Sprintf("%v %v  `json:\"%v\"`", str, s, k)
	case reflect.Slice:
		s := subSlice(v, dep+1)
		str = fmt.Sprintf("%v []%v `json:\"%v\"`", str, s, k)
	default:
		str = fmt.Sprintf("%v %v `json:\"%v\"`", str, kind, k)
	}
	return
}

func subSlice(v interface{}, dep int) (str string) {
	i := v.([]interface{})
	for _, vi := range i {
		vtype := reflect.TypeOf(vi).Kind()

		if vtype == reflect.Slice {
			str += subSlice(vi, dep+1)
			continue
		}
		if vtype == reflect.Map {
			str += subMap(vi, dep+1)
		} else {
			str = fmt.Sprintf("%v", vtype)
			return
		}
	}
	return
}

func subMap(v interface{}, dep int) (str string) {

	var space string
	var endSpace string
	for i := 0; i < (dep)*4; i++ {
		space += " "
	}
	for i := 0; i < (dep-1)*4; i++ {
		endSpace += " "
	}

	str = "struct { \n"
	m := v.(map[string]interface{})
	for k, v := range m {
		str += space + pasrKey(k)
		kind := reflect.TypeOf(v).Kind()
		switch kind {
		case reflect.Map:
			subMap(v, dep+1)
		case reflect.Slice:
			s := subSlice(v, dep+1)
			str = space + fmt.Sprintf("%v []%v `json:\"%v\"` \n", str, s, k)
		default:
			str = fmt.Sprintf("%v  %v  `json:\"%v\"` \n", str, kind, k)
		}
	}
	str += endSpace + "}"
	return
}
